
/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

__IO FIFOBuf usart1tx;
__IO uint8_t usart1tx_buf[usart1tx_buf_len];
extern __IO uint8_t RigTemperature, RigConnectOK;
__IO uint8_t RigResponseTest;
extern __IO uint32_t RigNonresponseCounter;
__IO uint8_t timer_RS485DE_enable;
__IO uint8_t timer_RS485DE_disable;
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Configures the USART Peripheral.
  * @param  None
  * @retval None
  */
void USART_Config(void)
{
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
 
  usart1tx.len = usart1tx_buf_len;
  usart1tx.buf = usart1tx_buf;

  /* Enable GPIO clock */
  RCC_AHBPeriphClockCmd(USARTx_TX_GPIO_CLK | USARTx_RX_GPIO_CLK | USARTx_DIR_GPIO_CLK, ENABLE);
  
  /* Enable USART clock */
  USARTx_APBPERIPHCLOCK(USARTx_CLK, ENABLE);
  
  /* Connect PXx to USARTx_Tx */
  GPIO_PinAFConfig(USARTx_TX_GPIO_PORT, USARTx_TX_SOURCE, USARTx_TX_AF);
  GPIO_PinAFConfig(USARTx_RX_GPIO_PORT, USARTx_RX_SOURCE, USARTx_RX_AF);
  //GPIO_PinAFConfig(USARTx_DIR_GPIO_PORT, USARTx_DIR_SOURCE, USARTx_DIR_AF);
  
  /* Configure USART Tx and Rx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Pin = USARTx_TX_PIN;
  GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = USARTx_RX_PIN;
  GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Pin = USARTx_DIR_PIN;
  GPIO_Init(USARTx_DIR_GPIO_PORT, &GPIO_InitStructure);
  //GPIO_SetBits(USARTx_DIR_GPIO_PORT, USARTx_DIR_PIN);

  /* USARTx configuration ----------------------------------------------------*/
  /* USARTx configured as follow:
  - BaudRate = 38400 baud  
  - Word Length = 8 Bits
  - One Stop Bit
  - No parity
  - Hardware flow control disabled (RTS and CTS signals)
  - Receive and transmit enabled
  */
  USART_StructInit(&USART_InitStructure);

  USART_InitStructure.USART_BaudRate = USART_BAUDRATE;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USARTx, &USART_InitStructure);
  
  /* NVIC configuration */
  /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USARTx_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* Enable USART */
  USART_Cmd(USARTx, ENABLE);
}

int8_t USART_sendarray(uint8_t* arr, uint8_t n)
{
  int8_t result = -1;
  uint16_t i = 0;

  // If since last packet transmission there was no response, then bad
  if (!RigResponseTest)
  {
    // Set connection OK flag to 0
    RigConnectOK = 0;
    // Increase no reponse counter
    RigNonresponseCounter++;
  }

  while(1)
  {
    result = FBCopyFromArray(&usart1tx, arr, n);
    if (result == -1) continue;
    else break;
  }
  if (result != 0) return result;

  // Enable RS485 DE
  GPIO_SetBits(USARTx_DIR_GPIO_PORT, USARTx_DIR_PIN);

  // Wait some time
  //i = 0xFF;
  //while(--i != 0);

  // Enable the USARTx transmit data register empty interrupt
  USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);

  // Set rig response flag to 0
  RigResponseTest = 0;

  return 0;
}

void USART_Handler (void)
{
  uint16_t i = 0;
  
  if (USART_GetITStatus(USARTx, USART_IT_TXE) == SET) //check if TXE IRQ happened
  {
    if(usart1tx.rdIdx != usart1tx.wrIdx)
    {
      USART_SendData(USARTx, usart1tx.buf[usart1tx.rdIdx]);
      FBPtrInc(&usart1tx, &usart1tx.rdIdx);
    }
    else
    {
      // Disable transmission interrupt (itself)
      USART_ITConfig(USARTx, USART_IT_TXE, DISABLE); 
      
      // Wait some time
      //i = 0xFF;
      //while(--i != 0);
      // Disable RS485 DE
      //GPIO_ResetBits(USARTx_DIR_GPIO_PORT, USARTx_DIR_PIN);
      
      // Enable receiver
      //USART_DirectionModeCmd(USARTx, USART_Mode_Rx, ENABLE);
      // Enable receive interrupt
      //USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
    }
  }

  if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) //check if receive IRQ happened
  {
    // Get the temperature data
    RigTemperature = USART_ReceiveData(USARTx);
    // Set test variable to 1 (it was cleared when a packet was sent)
    RigResponseTest = 1;
    // Set connection OK status flag
    RigConnectOK = 1;
    // Disable reception interrupt (itself)
    //USART_ITConfig(USARTx, USART_IT_RXNE, DISABLE);
    // Disable receiver
    //USART_DirectionModeCmd(USARTx, USART_Mode_Rx, DISABLE);
  }
}
